package mspbots.xero.data.core.synclogs;

import com.fasterxml.jackson.databind.JsonNode;
import lombok.RequiredArgsConstructor;
import mspbots.xero.data.core.AbstractToolsUtil;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.relational.core.query.Criteria;
import org.springframework.data.relational.core.query.Query;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

/**
 * mspbots.cw.data.core.synclogs.SyncLogsService
 *
 * @author <a href="https://github.com/vnobo">Alex bob</a>
 * @date Created by 2020/10/19
 */
@Service
@RequiredArgsConstructor
public class SyncLogsServiceImpl extends AbstractToolsUtil {

    private final SyncLogsRepository logsRepository;

    public Mono<Page<SyncLogs>> search(Long tenantId, SyncLogsRequest queryParams, Pageable pageable) {

        Query query=Query.query(buildCriteria(tenantId,queryParams));
        Flux<SyncLogs> contents = this.r2dbcEntityTemplate.select(SyncLogs.class)
                .matching(query.with(pageable)).all();

        Mono<Long> count = this.r2dbcEntityTemplate.count(query,SyncLogs.class);

        return contents.collectList().zipWith(count).flatMap(objects ->
                Mono.just(new PageImpl<>(objects.getT1(), pageable, objects.getT2())));
    }

    public Flux<SyncLogs> find(Long tenantId, SyncLogsRequest queryParams, Pageable pageable) {

        Query query=Query.query(buildCriteria(tenantId,queryParams));
        return this.r2dbcEntityTemplate.select(SyncLogs.class)
                .matching(query.with(pageable)).all();

    }

    private Criteria buildCriteria(Long tenantId, SyncLogsRequest queryParams){
        Criteria criteria = Criteria.from(Criteria.where("tenantId").is(tenantId));
        criteria = criteria.and("time").between(queryParams.getStartTime(), queryParams.getEndTime());
        if (!ObjectUtils.isEmpty(queryParams.getAction())) {
            criteria = criteria.and("action").is(queryParams.getAction());
        }
        return criteria;
    }

    public Mono<JsonNode> count(Long tenantId, SyncLogsRequest queryParams) {
        Query query=Query.query(buildCriteria(tenantId,queryParams));
        return this.r2dbcEntityTemplate.count(query,SyncLogs.class)
                .map(result -> this.objectMapper.createObjectNode().put("result", result));
    }

    public Flux<StatsResponse> stats(Long tenantId) {
        return this.logsRepository.stats(tenantId);
    }
}
